from elftools.elf.elffile import ELFFile
import io
import struct
import sys

bpf_insn_template = """\
{
\t\t.code    = 0x%x,
\t\t.dst_reg = BPF_REG_%d,
\t\t.src_reg = BPF_REG_%d,
\t\t.off     = %d,
\t\t.imm     = %d\t/*%s*/
\t}\
"""

def parse_bpf(bytecode):
    list_of_insns = []
    for b_offset in range(0, len(bytecode), 8):
        instruction = bytecode[b_offset : b_offset + 8]
        opcode, src_and_dst, offset, imm = struct.unpack("BBhi", instruction[0:8])
        dst_reg, src_reg = src_and_dst & 0x0F, (src_and_dst & 0xF0) >> 4
        list_of_insns.append( (opcode, dst_reg, src_reg, offset, imm) )
    return list_of_insns

def process_file(f, section):
    elffile = ELFFile(f)

    symtab = elffile.get_section_by_name(".symtab")
    symtab_syms = list(symtab.iter_symbols())

    s = elffile.get_section_by_name(section)
    list_of_insns = parse_bpf(s.data())

    reladyn = elffile.get_section_by_name('.rel' + section)

    list_of_relocs = []
    if reladyn:
        for reloc in reladyn.iter_relocations():
            s = symtab_syms[reloc['r_info_sym']]
            list_of_relocs.append( (reloc['r_info_type'], reloc['r_offset'], s.name) )

    return list_of_insns, list_of_relocs

filename = sys.argv[1]
f = io.BytesIO(open(filename, 'rb').read())

print('''\
/* AUTOGENERATED DO NOT EDIT */
#include <linux/bpf.h>
#include <stddef.h>
#include <stdint.h>

#include "tbpf.h"
''')

for section in sys.argv[2:]:
    list_of_insns, list_of_relocs = process_file(f, section)

    insns = []
    for i, (opcode, dst_reg, src_reg, offset, imm) in enumerate(list_of_insns):
        r = ''
        for t, o, n in list_of_relocs:
            if o / 8 == i:
                r = ' relocation for %s ' % (n,)
        s = bpf_insn_template % (opcode, dst_reg, src_reg, offset, imm, r)
        insns.append( s )


    print('''\
size_t bpf_insn_%s_cnt = %s;

struct bpf_insn bpf_insn_%s[] = {
\t%s};\
''' % (section, len(insns), section, ', '.join(insns)))

    reloc_template = '''\
{
\t\t.name = %s,
\t\t.type = %d,
\t\t.offset = %d
\t}\
'''
    relocs = []
    for t, o, n in list_of_relocs + [(False, 0, 0)]:
        s = reloc_template % ('"' + n + '"' if n else 'NULL', t, o / 8)
        relocs.append(s)

    print('''

struct tbpf_reloc bpf_reloc_%s[] = {
\t%s};
''' % (section, ', '.join(relocs)))
